package com.dawn.iiotgateway.daemon;

import com.dawn.iiotgateway.entity.OfflineMessage;
import com.dawn.iiotgateway.service.IOfflineMessageService;
import com.dawn.iiotgateway.utils.Timestamp;
import jakarta.annotation.PostConstruct;
import org.eclipse.paho.client.mqttv3.*;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;


@Service
public class MqttService {

    @Autowired
    private IOfflineMessageService offlineMessageService;

    private MqttClient client;
    private String clientId = "iiotgateway-001";
    private MemoryPersistence persistence;

    private String broker = "tcp://127.0.0.1:1883";
    private String subTopic = "/fromCloud";
    private String pubTopic = "/toCloud";

    @PostConstruct
    public void initService(){

        // api-key:    8659708eb8779f16
        // secret-key:  ShkK08of9BKnC9CdZHySq1E4ASEZXPwqfflZuhUeY49A1L
        MemoryPersistence persistence = new MemoryPersistence();

        try{
            client = new MqttClient(broker, clientId, persistence);

            // MQTT 连接选项
            MqttConnectOptions connOpts = new MqttConnectOptions();
            connOpts.setUserName("8659708eb8779f16");
            connOpts.setPassword("ShkK08of9BKnC9CdZHySq1E4ASEZXPwqfflZuhUeY49A1L".toCharArray());
            // 保留会话
            connOpts.setCleanSession(true);

            // 设置回调
            client.setCallback(new MqttCallback() {

                @Override
                public void connectionLost(Throwable cause) {
                    // 连接丢失后，一般在这里面进行重连
                    System.out.println("连接断开，可以做重连");
                }

                @Override
                public void messageArrived(String topic, MqttMessage message) throws Exception {
                    // subscribe后得到的消息会执行到这里面
                    System.out.println("接收消息主题:" + topic);
                    System.out.println("接收消息Qos:" + message.getQos());
                    System.out.println("接收消息内容:" + new String(message.getPayload()));
                }

                @Override
                public void deliveryComplete(IMqttDeliveryToken token) {
                    System.out.println("deliveryComplete---------" + token.isComplete());
                }
            });

            // 建立连接
            System.out.println("#### Connecting to broker: " + broker);
            client.connect(connOpts);
            System.out.println("#### Connected ####");

            // 订阅
            client.subscribe(subTopic);

        }catch (MqttException me) {
            me.printStackTrace();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

    }

    public void subScribe(){

        try{
            client.subscribe(pubTopic, new IMqttMessageListener() {
                @Override
                public void messageArrived(String s, MqttMessage mqttMessage) throws Exception {

                }
        });
        }catch(MqttException me) {
            me.printStackTrace();
        }
    }

    public void unsubScribe(){

        try{
            client.unsubscribe(pubTopic);
        }catch(MqttException me) {
            me.printStackTrace();
        }

    }

    public void publishMessage(String content) {

        try {

            // 如果没有连接到服务器，则需要先保存到本机
            if(!client.isConnected()){
                offlineMessageService.save(new OfflineMessage(false, Timestamp.now(), content));
                System.out.println("#### offlineMessageService saved ####");
                return;
            }

            System.out.println("#### Publishing mqtt message: " + content + " ####");

            // 消息发布所需参数
            MqttMessage message = new MqttMessage(content.getBytes());
            message.setQos(2);
            client.publish(pubTopic, message);

            System.out.println("#### mqtt Message published ####");

        } catch (MqttException me) {
            System.out.println("reason " + me.getReasonCode());
            System.out.println("msg " + me.getMessage());
            System.out.println("loc " + me.getLocalizedMessage());
            System.out.println("cause " + me.getCause());
            System.out.println("excep " + me);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}
